import { useState, useEffect, useRef } from 'react';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import './App.css';
import { Transaction } from '@mysten/sui/transactions';
import { CONTRACT_ADDRESS } from './constant';
import { client } from './rpc';
import { getFaucetHost, requestSuiFromFaucetV0 } from '@mysten/sui/faucet';


interface ChatEvent {
	msg: string;
	sender: string;
}

function App() {
	const [msg, setMsg] = useState('');
	const [fetchedMessages, setFetchedMessages] = useState<string[]>([]);
	// 在组件中使用 useRef 创建一个引用来引用消息展示区域
	const messageBoxRef = useRef<HTMLDivElement>(null);

	function generateNewAddress() {
		const keypair = new Ed25519Keypair();
		const address = keypair.getPublicKey().toSuiAddress();
		return { keypair, address };
	}

	const requestSuiGas = async (recipient: string) => {
		await requestSuiFromFaucetV0({
			host: getFaucetHost('devnet'),
			recipient: recipient,
		});
	};

	async function send_msg() {

		setMsg(''); // 清空输入框内容
		const { keypair, address } = generateNewAddress();
		console.log('address:', address);
		await requestSuiGas(address);

		const tx = new Transaction();
		tx.moveCall({
			target: `${CONTRACT_ADDRESS}::suichat::send_msg`,
			arguments: [tx.pure.string(msg)],
		});
		const sign_result = await client.signAndExecuteTransaction({ transaction: tx, signer: keypair });
		console.log(sign_result);
	}

	async function fetch_msg() {
		const eventType = `${CONTRACT_ADDRESS}::suichat::NewMsg`;
		let allEvents: any[] = [];  // 用来存储所有事件
		let cursor = null;  // 初始的 cursor 为 null

		// 循环获取 events，直到 hasNextPage 为 false
		while (true) {
			const events = await client.queryEvents({
				cursor: cursor,
				limit: 50,
				order: 'ascending',
				query: {
					MoveEventType: eventType,
				},
			});

			// 将当前请求的事件数据加入 allEvents 数组
			allEvents = [...allEvents, ...events.data];

			// 如果还有下一页，更新 cursor；否则结束循环
			if (events.hasNextPage) {
				cursor = events.nextCursor;
			} else {
				break;
			}
		}

		// 先按 timestampMs 排序，如果 timestampMs 相同再按 event.id.eventSeq 排序
		const sortedEvents = allEvents
			.map((event) => ({ ...event })) // 保留原始事件数据
			.sort((a, b) => {
				// 按 timestampMs 排序
				const timestampA = a.timestampMs ? parseInt(a.timestampMs, 10) : 0;
				const timestampB = b.timestampMs ? parseInt(b.timestampMs, 10) : 0;

				if (timestampA !== timestampB) {
					return timestampA - timestampB; // 如果时间戳不同，按照时间戳排序
				}

				// 如果时间戳相同，则按 eventSeq 排序
				const eventSeqA = a.id?.eventSeq ? parseInt(a.id.eventSeq, 10) : 0;
				const eventSeqB = b.id?.eventSeq ? parseInt(b.id.eventSeq, 10) : 0;
				if (eventSeqA !== eventSeqB) {
					return eventSeqA - eventSeqB; // 如果时间戳相同，则按照 eventSeq 排序
				}

				// 如果 eventSeq 也相同，则按 address（sender）字母排序
				const senderA = a.sender || '';
				const senderB = b.sender || '';
				return senderA.localeCompare(senderB); // 按照 sender 地址字母升序排序
			});

		const messages = sortedEvents.map((event) => {

			// 将 timestampMs 转为 Date 对象
			const timestamp = event.timestampMs ? new Date(parseInt(event.timestampMs, 10)) : new Date();

			// 格式化成 年-月-日 时:分:秒
			const year = timestamp.getFullYear();
			const month = (timestamp.getMonth() + 1).toString().padStart(2, '0');  // 月份从0开始，需要+1并格式化成2位数
			const day = timestamp.getDate().toString().padStart(2, '0');
			const hours = timestamp.getHours().toString().padStart(2, '0');
			const minutes = timestamp.getMinutes().toString().padStart(2, '0');
			const seconds = timestamp.getSeconds().toString().padStart(2, '0');

			const formattedTime = `[${year}-${month}-${day} ${hours}:${minutes}:${seconds}]`;

			const data = event.parsedJson as ChatEvent; // 类型断言
			const shortSender = `${formattedTime} ${data.sender.slice(0, 6)}...${data.sender.slice(-4)}`;
			return `${shortSender}: ${data.msg}`;
		});

		setFetchedMessages(messages);
	}

	// 每 1s 自动 fetch_msg
	useEffect(() => {
		const interval = setInterval(fetch_msg, 1000);
		return () => clearInterval(interval);
	}, []);

	// 处理回车事件
	const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
		if (e.key === 'Enter') {
			if (e.shiftKey) {
				// Shift + Enter: 插入换行符
				setMsg(msg + '\n');
			} else {
				// Enter: 发送消息
				send_msg();
			}
			e.preventDefault(); // 防止回车键输入换行符
		}
	};

	useEffect(() => {
		// 监听 fetchedMessages 更新，自动滚动到底部
		if (messageBoxRef.current) {
			messageBoxRef.current.scrollTop = messageBoxRef.current.scrollHeight;
		}
	}, [fetchedMessages]);  // 每次更新消息时触发滚动

	return (
		<div className="app">
			<h1 className="title">Sui Chat v1.0</h1>

			<button
				className="view-contract-button"
				onClick={() => window.open(`https://devnet.suivision.xyz/package/${CONTRACT_ADDRESS}`, '_blank')}
			>
				View Contract
			</button>

			{/* 醒目提示条 */}
			<div className="alert-bar">
				<strong>Notice:</strong> Messages will be retained for 1 day only.
			</div>

			{/* 消息展示区 */}
			<div className="message-box" ref={messageBoxRef}>
				{fetchedMessages.map((message, index) => (
					<div key={index} className="message">{message}</div>
				))}
			</div>

			{/* 底部输入区 */}
			<div className="input-container">
				<textarea
					value={msg}
					onChange={(e) => setMsg(e.target.value)}
					onKeyDown={handleKeyDown}
					placeholder="Enter message..."
					className="input-box"
				/>
				<button className="send-button" onClick={send_msg}>Send</button>
			</div>
		</div>
	);
}

export default App;
